use std::fs;

use log4rs::append::console::ConsoleAppender;
use log4rs::append::file::FileAppender;
use log4rs::Config;
use log4rs::config::{Appender, Root};
use log::LevelFilter;
use tauri::{ActivationPolicy, SystemTray};

use crate::{dao, migrate, state};
use crate::application::application::handlers::tray_event_handler::tray_event_handler;
use crate::runtime::error::MagicBoxError;
use crate::runtime::response::Code;
use crate::shortcut::shortcut;

pub fn run() -> tauri::Result<()> {
    // builder
    let mut builder = tauri::Builder::default().system_tray(SystemTray::new()).on_system_tray_event(tray_event_handler);

    builder = builder.setup(|app| {
        #[cfg(target_os = "macos")]
        // 隐藏任务栏与dock图标
        app.set_activation_policy(ActivationPolicy::Accessory);

        // 保留全局应用处理器对象
        state::application::application_mut().init_app(app.handle());

        // 处理本地数据路径
        let data_path = app.path_resolver().app_local_data_dir().expect("无法获取应用本地数据目录");
        fs::create_dir_all(data_path.clone()).expect(format!("无法创建应用本地数据目录：{}", data_path.to_str().unwrap()).as_str());

        // 处理本地日志路径
        let log_path = app.path_resolver().app_log_dir().expect("无法获取应用本地日志目录");
        fs::create_dir_all(log_path.clone()).expect(format!("无法创建应用日志目录：{}", log_path.to_str().unwrap()).as_str());

        // 初始化日志
        init_logger();
        log::debug!("应用数据目录: {}", data_path.to_str().unwrap());
        log::debug!("应用日志目录: {}", log_path.to_str().unwrap());

        // 建立主数据库连接
        let result = dao::connection::connect();
        if result.is_err() {
            log::error!("主数据库连接失败：{}", result.unwrap_err().to_string());

            return Err(Box::new(MagicBoxError::new(Code::UndefinedError, "连接数据库失败")));
        }

        // 建立组件-V2ray数据库连接
        let result = dao::connection::components::v2ray::connect();
        if result.is_err() {
            log::error!("组件-V2ray数据库连接失败：{}", result.unwrap_err().to_string());

            return Err(Box::new(MagicBoxError::new(Code::UndefinedError, "连接数据库失败")));
        }

        // 数据库迁移
        let result = migrate::migrate::run();
        if result.is_err() {
            log::error!("数据库迁移失败：{}", result.err().unwrap());

            return Err(Box::new(MagicBoxError::new(Code::UndefinedError, "数据库迁移失败")));
        }

        // 注册全局快捷键
        shortcut::register_global_hotkey();

        Ok(())
    });

    Ok(crate::application::application::invokes::invoke::register_invokes(builder).build(tauri::generate_context!())?.run(crate::application::application::handlers::app_event_handler::app_event_handler))
}

/// 初始化日志处理器
fn init_logger() {
    let path = state::application::application().app().path_resolver().app_log_dir().unwrap().join("main.log");
    let fa = FileAppender::builder().build(path.clone()).expect(format!("无法打开日志文件: {}", path.to_str().unwrap()).as_str());

    let mut level = LevelFilter::Error;
    // 开发环境设置日志级别
    if cfg!(debug_assertions) {
        level = LevelFilter::Debug;
    }

    let mut cb = Config::builder();

    cb = cb.appender(Appender::builder().build("stdout", Box::new(ConsoleAppender::builder().build())));
    cb = cb.appender(Appender::builder().build("main", Box::new(fa)));

    let root = Root::builder().appenders(vec!["stdout", "main"]).build(level);
    let config = cb.build(root).expect("初始化日志配置失败");

    log4rs::init_config(config).expect("初始化日志处理器失败");
}